package com.zxmzy.scaffold.core.widget.slideback

import android.app.Activity
import android.content.Context
import android.content.ContextWrapper
import android.view.MotionEvent
import android.view.ViewGroup
import android.view.ViewParent
import android.widget.FrameLayout
import com.zxmzy.scaffold.core.ext.dp
import kotlin.math.abs

/**
 * @author zhangxiaoming
 * @date 2023/8/31
 * @description
 */
class SlideControlLayout(
    context: Context,
    private val canSlideWidth: Int,
    slideView: ISlideView,
    private val onSlide: OnSlide? = null
) : FrameLayout(context) {
    private val slideBackView: SlideBackView
    private var enable: Boolean = true
    private var downX: Float = 0f
    private var moveX: Float = 0f
    private var startDrag: Boolean = false

    init {
        slideBackView = SlideBackView(context, slideView)
        addView(slideBackView)
    }

    fun attachToActivity(activity: Activity): SlideControlLayout {
        val parent: ViewParent? = parent
        if (parent is ViewGroup) {
            parent.removeView(this)
        }
        val decor: ViewGroup = activity.window.decorView as ViewGroup
        decor.addView(
            this,
            ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT
            )
        )
        return this
    }

    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        if (!enable) return false
        if (ev.action == MotionEvent.ACTION_DOWN) {
            if (ev.rawX <= canSlideWidth) {
                return true
            }
        }
        return super.onInterceptTouchEvent(ev)
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        if (!enable) {
            return super.onTouchEvent(event)
        }
        var currentX: Float = event.rawX
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                val currentY = event.rawY
                if (currentY > 100.dp() && currentX <= canSlideWidth) {
                    downX = currentX
                    startDrag = true
                    slideBackView.updateRate(0f, false)
                    setSlideViewY(slideBackView, event.rawY.toInt())
                }
            }

            MotionEvent.ACTION_MOVE -> {
                if (startDrag) {
                    moveX = currentX - downX
                    if (abs(moveX) <= slideBackView.width * 2) {
                        slideBackView.updateRate(abs(moveX) / 2, false)
                    } else {
                        slideBackView.updateRate(slideBackView.width.toFloat(), false)
                    }
                    setSlideViewY(slideBackView, event.rawY.toInt())
                }
            }

            MotionEvent.ACTION_UP,
            MotionEvent.ACTION_CANCEL,
            MotionEvent.ACTION_OUTSIDE -> {
                if (startDrag && moveX >= slideBackView.width * 2) {
                    onBack()
                    slideBackView.updateRate(0f, false)
                } else {
                    slideBackView.updateRate(0f, startDrag)
                }
                moveX = 0f
                startDrag = false
            }
        }
        return startDrag || super.onTouchEvent(event)
    }

    private fun onBack() {
        if (onSlide == null) {
            getActivityContext(context)?.onBackPressed()
        } else {
            onSlide.onSlideBack()
        }
    }

    private fun setSlideViewY(view: SlideBackView, y: Int) {
        if (!view.getSlideView().scrollVertical()) {
            scrollTo(0, 0)
            return
        }
        scrollTo(0, -(y - view.height / 2))
    }

    private fun getActivityContext(context: Context): Activity? {
        return when (context) {
            is Activity -> {
                context
            }

            is ContextWrapper -> {
                getActivityContext(context)
            }

            else -> {
                null
            }
        }
    }
}